package cn.wh.netty.handler;

import cn.wh.enums.MsgActionEnum;
import cn.wh.netty.pojo.DataContent;
import cn.wh.netty.pojo.Msg;
import cn.wh.service.UserServer;
import cn.wh.utils.JsonUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;


/**
 * 用于处理消息的handler
 * 由于它的传输数据的载体是frame，这个frame 在netty中，是用于为websocket专门处理文本对象的，frame是消息的载体，此类叫：TextWebSocketFrame
 */
@Component
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    //用于记录和管理所有客户端的channel
    public static ChannelGroup users = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    public static HashMap<String, Channel> userChannel = new HashMap<>();

    private static UserServer userServer;

    @Autowired
    public void setChatServiceImpl(UserServer userServer) {
        ChatHandler.userServer = userServer;
    }

    /**
     * 用户发送数据监听器
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        //获取客户端所传输的json字符串内容
        String jsonStr = msg.text();
        //1、获取消息内容
        DataContent dataContent = JsonUtils.jsonToPojo(jsonStr, DataContent.class);

        System.out.println(dataContent);
        //获取消息类型
        Integer action = dataContent.getAction();
        //channel通道
        Channel channel = ctx.channel();
        //解析内容
        Msg contentMsg = dataContent.getMsg();
        String sendId = contentMsg.getSendId();
        String receiveId = contentMsg.getReceiveId();
        //判断消息类型
        if (action.equals(MsgActionEnum.CONNECT.type)) {
            //第一次连接
            //获取发送id建立channel与userId的关联
            userChannel.put(sendId, channel);
        } else if (action.equals(MsgActionEnum.CHAT.type)) {
            DataContent dataContentMsg = new DataContent();
            //第二次聊天类型 并且持久化数据库
//            String content = contentMsg.getContent();
//            Integer type = contentMsg.getType();
//            String receiveId = contentMsg.getReceiveId();
            //持久化数据库 并且标记未签收
            dataContentMsg.setMsg(contentMsg);
            //获取接收方的通道
            Channel receiveChannel = userChannel.get(receiveId);
            String extand = dataContent.getExtand();
            if ("video".equals(extand)) {
                //启动音视频 向对方推送房间号
                if (receiveChannel == null) {
                    //离线状态 //通知 没有在线
                    dataContentMsg.setExtand("video-stop");
                    channel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContentMsg)));
                } else {
                    dataContentMsg.setExtand(extand);
                    channel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContentMsg)));
                    receiveChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContentMsg)));
                }
            } else {
                // 图片和文本
                String msgId = userServer.saveMsg(contentMsg);
                contentMsg.setMsgId(msgId);
                if (receiveChannel == null) {
                    //离线状态
                } else {
                    receiveChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContentMsg)));
                }
            }
        } else if (action.equals(MsgActionEnum.SIGNED.type)) {

        } else if (action.equals(MsgActionEnum.KEEPALIVE.type)) {

        }


    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("有客户端连接..................");
        users.add(ctx.channel());
    }


    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        users.remove(ctx.channel());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        //发生了异常后关闭连接，同时从channelgroup移除
        ctx.channel().close();
        users.remove(ctx.channel());
    }
}
